//  Inside Microsoft Exchange 2007 Web Services 
//  Chapter 14
//
//  Copyright (c) 2007 David Sterling, Ben Spain, Mark Taylor, Huw Upshall, Michael Mainer.  
//  All rights reserved.
//

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using ProxyHelpers.EWS;

namespace InspectorsAndExcludes
{
    class Program
    {
        /// <summary>
        /// Enumeration for Inspection state (Listing 14-4)
        /// </summary>
        [Flags]
        public enum InspectionState
        {
            None = 0,
            Inspector1 = 1,
            Inspector2 = 2,
            Inspector3 = 4,
            Urgent = 8,
        }

        static void Main(string[] args)
        {
            ExchangeServiceBinding binding = new ExchangeServiceBinding();
            binding.Url = @"https://yourServer/ews/Exchange.asmx";
            binding.Credentials = new NetworkCredential(
                "username",
                "password",
                "domain");

            // TODO: You need a valid ItemId in order to call StampItemWithInspectionState
            // StampItemWithInspectionState(
            //                    binding,
            //                    yourItemId,
            //                    InspectionState.Inspector1);

            FindItemsForInspector(binding, InspectionState.Inspector2);
        }

        // Declare our Guid
        public static readonly Guid InspectionGuid =
           new Guid("{a879806c-03df-4750-a2b1-85ef625f959b}");
        public static readonly String InspectionStatePropertyName = "Inspection State";

        /// <summary>
        /// Stamp an existing item with our InspectionState (Listing 14-15)
        /// </summary>
        /// <param name="binding">Service binding to use for the UpdateItem 
        /// call</param>
        /// <param name="id">Id of existing item to stamp</param>
        /// <param name="inspectionState">Inspection state</param>
        /// 
        public static void StampItemWithInspectionState(
                           ExchangeServiceBinding binding,
                           ItemIdType id,
                           InspectionState inspectionState)
        {
            UpdateItemType updateRequest = new UpdateItemType();
            updateRequest.ConflictResolution = ConflictResolutionType.AutoResolve;
            updateRequest.MessageDisposition = MessageDispositionType.SaveOnly;
            updateRequest.MessageDispositionSpecified = true;
            SetItemFieldType setItemField = new SetItemFieldType();

            // Notice that I am using the ExtendedProperty extensions that I wrote 
            // in Chapter 13
            //
            PathToExtendedFieldType inspectionStatePath =
                     PathToExtendedFieldType.BuildGuidName(
                            InspectionGuid,
                            InspectionStatePropertyName,
                            MapiPropertyTypeType.Integer);

            // We want to get the numeric value for this flags combination
            //
            ExtendedPropertyType inspectionStateProperty =
                     new ExtendedPropertyType(
                             inspectionStatePath,
                             ((int)inspectionState).ToString());
            MessageType updateMessage = new MessageType();
            updateMessage.ExtendedProperty = new ExtendedPropertyType[] { 
             inspectionStateProperty };

            setItemField.Item = inspectionStatePath;
            setItemField.Item1 = updateMessage;
            ItemChangeType itemChange = new ItemChangeType();
            itemChange.Item = id;
            itemChange.Updates = new ItemChangeDescriptionType[] { setItemField };
            updateRequest.ItemChanges = new ItemChangeType[] { itemChange };
            UpdateItemResponseType response = binding.UpdateItem(updateRequest);

            if (response.ResponseMessages.Items[0].ResponseCode != ResponseCodeType.NoError)
            {
                throw new Exception("Stamping operation failed with response code: " +
                    response.ResponseMessages.Items[0].ResponseCode.ToString());
            }
        }

        /// <summary>
        /// Finds the items that the passed inspector has NOT seen (Listing 14-16)
        /// </summary>
        /// <param name="binding">Binding to use for the call</param>
        /// <param name="inspector">Inspector to examine items for</param>
        /// <returns>List of matching items</returns>
        /// 
        public static List<ItemIdType> FindItemsForInspector(
                             ExchangeServiceBinding binding,
                             InspectionState inspector)
        {
            FindItemType request = new FindItemType();
            PathToExtendedFieldType inspectionStatePath =
                     PathToExtendedFieldType.BuildGuidName(
                              InspectionGuid,
                              InspectionStatePropertyName,
                              MapiPropertyTypeType.Integer);
            ExcludesType excludes = new ExcludesType();
            excludes.Item = inspectionStatePath;
            excludes.Bitmask = new ExcludesValueType();
            excludes.Bitmask.Value = ((int)inspector).ToString();

            request.Restriction = new RestrictionType();
            request.Restriction.Item = excludes;
            request.ItemShape = new ItemResponseShapeType();
            request.ItemShape.BaseShape = DefaultShapeNamesType.Default;
            request.Traversal = ItemQueryTraversalType.Shallow;
            DistinguishedFolderIdType drafts = new DistinguishedFolderIdType();

            drafts.Id = DistinguishedFolderIdNameType.drafts;
            request.ParentFolderIds = new BaseFolderIdType[] { drafts };
            FindItemResponseType response = binding.FindItem(request);
            FindItemResponseMessageType responseMessage =
            response.ResponseMessages.Items[0] as FindItemResponseMessageType;
            if (responseMessage.ResponseCode != ResponseCodeType.NoError)
            {
                throw new Exception("FindItemsForInspector failed with response code: " +
                      responseMessage.ResponseCode.ToString());
            }
            List<ItemIdType> result = new List<ItemIdType>();

            // We did a normal find item (not grouped), so we should expect an array 
            // of real items back
            //
            ArrayOfRealItemsType realItems = (responseMessage.RootFolder.Item as
                        ArrayOfRealItemsType);
            foreach (ItemType item in realItems.Items)
            {
                result.Add(item.ItemId);
            }
            return result;
        }
    }
}
